package com.sinosoft.online.webservice.dto;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.sinosoft.online.webservice.constant.WebServiceConstants;
import com.sinosoft.online.webservice.util.XmlHandler;

/**
 * WebService服务请求对象
 * @author xiaoxiong
 *
 */
public class Request implements Serializable{

	private static final long serialVersionUID = 1L;

	private Header header;	//	请求头
	
	private Object content;	//	请求内容

	private String xmlStr;	//	XML字符串格式的请求消息
	
	private Document xmlDoc;	//	XML文本格式的请求消息
	
	/**
	 * 根据请求字符串文本生成Request对象
	 * @param xmlStr
	 */
	public Request(String xmlStr) {
		this.xmlStr = xmlStr;
		try {
			this.xmlDoc = DocumentHelper.parseText(this.xmlStr);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		this.header = (Header) XmlHandler.xmlStrToBean(
				this.getXmlChild(WebServiceConstants.MSG_HEADER_NODE).asXML(), Header.class);
	}
	
	/**
	 * 构建消息请求对象，消息内容为JavaBean或Map
	 * @param header	消息头
	 * @param bean	传输实体
	 */
	public Request(Header header, Object object) {
		this.header = header;
		this.content = object;
		this.xmlStr = this.toXmlString();
		System.out.println(xmlStr);
		try {
			this.xmlDoc = DocumentHelper.parseText(this.xmlStr);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 构建消息请求对象，消息内容为JavaBean和Map的混合对象
	 * @param header	消息头
	 * @param maps	键值对集合
	 */
	public Request(Header header, Object... object) {
		this.header = header;
		if(object != null) {
			if(object.length <= 1) {
				this.content = object;
			} else {
				List<Object> list = new ArrayList<Object>();
				for(int i=0; i<object.length; i++) {
					list.add(object[i]);
				}
				this.content = list;
			}
		}
		this.xmlStr = this.toXmlString();
		System.out.println(this.xmlStr);
		try {
			this.xmlDoc = DocumentHelper.parseText(this.xmlStr);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 将请求参数中的子节点数据绑定到相应的java对象中
	 * @param clazz	绑定的java对象类
	 * @return	绑定数据后的java对象
	 */
	public Object bindRequestData(Object bean) {
		Element element = this.xmlDoc.getRootElement().element(bean.getClass().getSimpleName());	//	根据对象类名获取相应的xml节点
		Object data = null;
		if(element != null) {
			data = XmlHandler.xmlElementToBean(element, bean);
		}
		return data;
	}
	
	/**
	 * 获取请求消息头
	 * @return	消息头
	 */
	public Header getHeader() {
		return this.header;
	}

	/**
	 * 获取请求消息内容
	 * @return	消息内容
	 */
	public Object getContent() {
		return this.content;
	}
	
	/**
	 * 获取带UCD节点的XML字符串格式的请求消息
	 * @return	XML字符串格式的请求消息
	 */
	public String getXmlStr() {
		return this.xmlStr;
	}
	
	/**
	 * 获取请求消息XML文本对象
	 * @return	请求消息XML文本对象
	 */
	public Document getXmlDoc() {
		return this.xmlDoc;
	}
	
	/**
	 * 获取请求参数集合
	 * @return	参数集合
	 */
	public Map<String, Object> getRequestParams() {
		return XmlHandler.xmlStrToMap(this.xmlStr);
	}
	
	/**
	 * 获取指定的请求参数值
	 * @param param	参数节点名称
	 * @return	参数值
	 */
	public Object getRequsetParamValue(String param) {
		Map<String, Object> params = XmlHandler.xmlStrToMap(this.xmlStr);
		if(params == null) {
			return null;
		} else {
			return params.get(param);
		}
	}
	
	/**
	 * request对象转换为xml格式的字符串
	 * @return	xml格式的字符串
	 */
	@SuppressWarnings("unchecked")
	private String toXmlString() {
		Element root = DocumentHelper.createElement(WebServiceConstants.MSG_REQUEST_ROOT);
		root.add(XmlHandler.beanToXmlElement(this.header));	//	添加消息头
		if(this.content == null) {
			return root.asXML();
		} else {
			if(this.content instanceof Map) {	//	消息内容为Map
				Map<String, String> map = (Map<String, String>) this.content;
				addMapContent(map, root);
			} else if(this.content instanceof List) {	//	消息内容为Map与JavaBean的混合对象
				List<Object> contents = (List<Object>) this.content;
				for(int i=0; i<contents.size(); i++) {
					Object object = contents.get(i);
					if(object instanceof Map) {
						addMapContent((Map<String, String>)object, root);
					} else {
						root.add(XmlHandler.beanToXmlElement(object, "serialVersionUID"));
					}
				}
			} else {	//	消息内容为JavaBean
				root.add(XmlHandler.beanToXmlElement(this.content, "serialVersionUID"));	//	添加回执内容
			}
			return root.asXML();
		}
	}
	
	/**
	 * 添加Map类的消息内容到Request的XML文本中
	 * @param map	键值对消息内容
	 * @param root	请求消息XML文本的根节点
	 */
	private void addMapContent(Map<String, String> map, Element root) {
		Iterator<String> iterator = map.keySet().iterator();
		while(iterator.hasNext()) {
			String next = iterator.next();
			Element child = DocumentHelper.createElement(next);
			child.setText(map.get(next));
			root.add(child);
		}
	}
	
	/**
	 * 获取xml格式消息的子节点
	 * @return	消息子节点
	 */
	private Element getXmlChild(String nodeName) {
        Element root = this.xmlDoc.getRootElement();  
        return root.element(nodeName);
	}
	
	public static void main(String[] args) {
		/*Header header = new Header("TCM_PLAT_06", WebServiceConstants.SYS_EMR_ID);
		Dict dict = new Dict();
		dict.addDictItem(new DictItem("1", "男"));
		Map<String, String> map = new HashMap<String, String> ();
		map.put("handleType", WebServiceConstants.MSG_HANDLETYPE_ADD);
		Request r = new Request(header, dict, map);
		System.out.print(r.getXmlStr());*/
	}
	
}
